package main

import (
	"fmt"
	"math"
	"math/cmplx"
)

//bb := true  //函数外面定义变量的时候，不能使用海象运算符
//函数外面定义的变量的作用域是：package
//var aa = 3
//var ss = "kkk"
//一行一行写比较啰嗦，可以用括号
var (
	aa = 3
	ss = "kkk"
	bb = true
)

func variableZeroValue() {
	var a int
	var s string

	fmt.Printf("%d %q \n", a, s)
}

func variableInitialValue() {
	var a, b int = 3, 4
	var s string = "abc"
	fmt.Println(a, b, s)
}

func variableTypeDeduction() {
	var a, b, c, s = 5, 6, true, "def"
	fmt.Println(a, b, c, s)
}

func variableShorter() {
	a, b, c, s := 5, 6, true, "def"
	b = 10
	fmt.Println(a, b, c, s)
}

func datatypeComplex() {
	c := 3 + 4i
	//复数取模
	fmt.Println(cmplx.Abs(c))
}

//欧拉公式
func euler() {
	fmt.Printf("%.3f",
		cmplx.Exp(1i*math.Pi)+1,
		//cmplx.Pow(math.E, 1i*math.Pi ) + 1,
	)
}

//勾股定理
func triangle() {
	var a, b = 3, 4
	//var c int
	//c = int(math.Sqrt(float64(a*a + b*b)))
	//fmt.Println(c)
	fmt.Println(calcTriangle(a, b))
}

// for test
func calcTriangle(a, b int) int {
	var c int
	c = int(math.Sqrt(float64(a*a + b*b)))
	return c
}

func consts() {
	//注意，go里变量名的大小写是有含义的，
	//所以不要一口气把变量名大写
	//const filename = "abc.txt"
	//const a, b = 3, 4
	const (
		filename = "abc.txt"
		a, b     = 3, 4
	)
	var c int
	//之前说了，go里没有隐式转换，所以必须强转
	//这里a,b没有强转（参见函数triagle），因为，定义常量a，b的时候，
	//没有指定类型，所以3和4既可以是数值也可以浮点
	//如果定义成：const a, b int = 3, 4
	//那么底下必须强转
	c = int(math.Sqrt(a*a + b*b))
	fmt.Println(c, filename)
}

func enums() {
	//go没有专门的枚举关键字，一般使用一组常量表示
	//const (
	//	cpp = 0
	//	java = 1
	//	python = 2
	//	golang = 3
	//)

	const (
		cpp = iota
		_
		python
		golang
		javascript
	)
	fmt.Println(cpp, javascript, python, golang)

	//b, kb, mb, gb, tb, pb
	const (
		b = 1 << (10 * iota)
		kb
		mb
		gb
		tb
		pb
	)
	fmt.Println(b, kb, mb, gb, tb, pb)
}

func main() {
	fmt.Println("hello world!")

	//变量声明
	variableZeroValue()
	variableInitialValue()
	variableTypeDeduction()
	variableShorter()
	fmt.Println(aa, bb, ss)

	//数据类型
	datatypeComplex()
	euler()

	//强制类型转换。golang没有隐式转换，只有显示类型转换
	triangle()

	//常量
	consts()

	//枚举类型，
	enums()
}
